package vip.specimen.system.service;

import com.alibaba.fastjson.JSONObject;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import vip.specimen.system.common.enums.ResultCode;
import vip.specimen.system.common.handler.SystemExceptionHandler;
import vip.specimen.system.datasource.entity.SystemRoleEntity;
import vip.specimen.system.datasource.entity.SystemUserEntity;
import vip.specimen.system.repository.SystemUserRepository;
import vip.specimen.system.datasource.validation.SystemUserEditPasswordValidation;
import vip.specimen.system.datasource.validation.SystemUserInsertValidation;
import vip.specimen.system.datasource.validation.SystemUserValidation;
import vip.specimen.system.utils.CommonUtil;
import vip.specimen.system.utils.DataBaseUtil;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.UUID;

/**
 * *@Author: 余浪人
 * *@Date：2021/2/22 16:53
 * *@Email:yulangren520@Gmail.com
 * *@QQ:1368419640
 **/
@Service
public class SystemUserService {
    @Autowired
    private SystemUserRepository systemUserRepository;
    @Autowired
    private SystemRoleService roleService;
    @Value("${system.init.manage.username}")
    private String username;
    @Value("${system.init.manage.password}")
    private String password;
    @Value("${system.init.manage.name}")
    private String name;
    @Value("${system.init.manage.gender}")
    private Integer gender;
    @Value("${system.init.manage.email}")
    private String email;
    @Value("${system.hash.hashIterations}")
    private int hashIterations;
    @Value("${system.hash.algorithmName}")
    private String algorithmName;
    @Resource
    private HttpServletRequest request;

    /**
     * 初始化管理员
     */
    @Transactional
    public void initialize() {
        if (this.systemUserRepository.count() < 1) {
            SystemUserEntity user = new SystemUserEntity();
            String salt = UUID.randomUUID().toString().substring(0, 6);
            user.setUsername(this.username);
            user.setPassword(this.encryptPassword(this.password, salt));
            user.setName(this.name);
            user.setEmail(this.email);
            user.setGender(this.gender);
            user.setSalt(salt);
            user.setAdmin(true);
            user.setEnable(true);
            user.setSystemRole(new ArrayList<SystemRoleEntity>() {{
                add(null);
            }});
            this.systemUserRepository.save(user);
        }
    }

    /**
     * 根据username 查询
     *
     * @param username 用户名
     * @return 用户
     */
    public SystemUserEntity findByUsername(String username) {
        return systemUserRepository.findByUsername(username);
    }

    /**
     * 根据电话查询
     *
     * @param phone 电话
     * @return result
     */
    public SystemUserEntity findByPhone(String phone) {
        return systemUserRepository.findByPhone(phone);
    }

    /**
     * 根据email 查询
     *
     * @param email email
     * @return result
     */
    public SystemUserEntity findByEmail(String email) {
        return systemUserRepository.findByEmail(email);
    }

    /**
     * 判断当前用户密码 输入是否正确
     *
     * @param password 原始密码
     * @return 结果
     */
    public boolean passwordIsCorrect(String password) {
        SystemUserEntity user = (SystemUserEntity) SecurityUtils.getSubject().getPrincipal();
        if (null == user) throw new SystemExceptionHandler(ResultCode.ERROR_NOT_LOGIN);
        SystemUserEntity userEntity = this.systemUserRepository.findByUuid(user.getUuid());
        return (userEntity.getPassword().equals(this.encryptPassword(password.length() > 0 ? password : "*.", userEntity.getSalt())));
    }

    /**
     * 更新密码
     *
     * @param passwordValidation 验证体
     * @return 用户
     */
    @Transactional
    public SystemUserEntity updatePassword(SystemUserEditPasswordValidation passwordValidation) {
        SystemUserEntity userEntity = this.systemUserRepository.findByUuid(passwordValidation.getUuid());
        userEntity.setPassword(this.encryptPassword(passwordValidation.getPassword(), userEntity.getSalt()));
        userEntity.setUpdateTime(Calendar.getInstance().getTime());
        this.systemUserRepository.save(userEntity);
        return userEntity;
    }

    /**
     * 明码转密码
     *
     * @param password 明码
     * @param salt     盐值
     * @return 密文
     */
    private String encryptPassword(String password, String salt) {
        return new SimpleHash(this.algorithmName, password, salt, this.hashIterations).toHex();
    }

    public Page<SystemUserEntity> findAll() {
        JSONObject param = CommonUtil.pageParams(this.request);
        return this.systemUserRepository.findAll(DataBaseUtil.getPageable(param.getIntValue("page"), param.getIntValue("pageSize"), DataBaseUtil.getSort("desc", "createTime")));
    }

    /**
     * 更新用户登录信息（登录ip,登录次数，最后登录时间）
     *
     * @param userEntity 用户
     */
    @Transactional
    public void updateLogin(SystemUserEntity userEntity, String ip) {
        userEntity.setLoginDegree(userEntity.getLoginDegree() + 1);
        userEntity.setLoginEndDate(Calendar.getInstance().getTime());
        userEntity.setLoginIp(ip);
        this.systemUserRepository.save(userEntity);
    }

    /**
     * 根据uuid更新用户信息
     *
     * @param uuid           uuid
     * @param userValidation 验证体
     * @return result
     */
    @Transactional
    public SystemUserEntity update(UUID uuid, SystemUserValidation userValidation) {
        if (this.systemUserRepository.existsById(uuid)) {
            SystemUserEntity userEntity = this.systemUserRepository.findByUuid(uuid);
            userEntity.setUpdateTime(Calendar.getInstance().getTime());
            userEntity.setAdmin(userValidation.isAdmin());
            userEntity.setEmail(userValidation.getEmail());
            userEntity.setGender(userValidation.getGender());
            userEntity.setName(userValidation.getName());
            userEntity.setPhone(userValidation.getPhone());
            userEntity.setPortrait(userValidation.getPortrait());
            userEntity.setAge(userValidation.getAge());
            userEntity.setSystemRole(this.roleService.findAllById(userValidation.getSystemRole()));
            return this.systemUserRepository.save(userEntity);
        }
        return null;
    }

    /**
     * 根据uuid查询
     *
     * @param uuid uuid
     * @return result
     */
    public SystemUserEntity findByUuid(UUID uuid) {
        return this.systemUserRepository.findByUuid(uuid);
    }

    /**
     * 添加用户
     *
     * @param userValidation 验证
     * @return 实体
     */
    @Transactional
    public SystemUserEntity insert(SystemUserInsertValidation userValidation) {
        String salt = UUID.randomUUID().toString().substring(0, 6);
        return this.systemUserRepository.save(new SystemUserEntity(
                userValidation.getUsername(), this.encryptPassword(userValidation.getPassword(), salt),
                userValidation.getName(), userValidation.getEmail(), userValidation.getPhone(), userValidation.getAge(),
                userValidation.getGender(), this.roleService.findAllById(userValidation.getSystemRole()), salt, userValidation.isAdmin(),
                userValidation.getPortrait()
        ));
    }

    /**
     * 根据uuid删除
     *
     * @param uuid uuid
     * @return result
     */
    @Transactional
    public boolean delete(UUID uuid) {
        SystemUserEntity user = (SystemUserEntity) SecurityUtils.getSubject().getPrincipal();
        if (null != user && user.getUuid().toString().equals(uuid.toString())) throw new SystemExceptionHandler(ResultCode.ERROR_NOT_EXECUTABLE_CURRENT);
        if (this.systemUserRepository.existsById(uuid)) {
            this.systemUserRepository.deleteById(uuid);
            return true;
        }
        return false;
    }

    /**
     * 根据uuid更新用户状态
     *
     * @param uuid uuid
     * @return result
     */
    public SystemUserEntity update(UUID uuid) {
        SystemUserEntity user = (SystemUserEntity) SecurityUtils.getSubject().getPrincipal();
        if (null != user && user.getUuid().toString().equals(uuid.toString())) throw new SystemExceptionHandler(ResultCode.ERROR_NOT_EXECUTABLE_CURRENT);
        if (this.systemUserRepository.existsById(uuid)) {
            SystemUserEntity userEntity = this.systemUserRepository.findByUuid(uuid);
            userEntity.setUpdateTime(Calendar.getInstance().getTime());
            userEntity.setEnable(!userEntity.isEnable());
            return this.systemUserRepository.save(userEntity);
        }
        return null;
    }

    /**
     * 根据用户名搜索用户
     *
     * @param username 用户名
     * @return 结果
     */
    public Page<SystemUserEntity> findByUsernameContainingOrderByCreateTimeDesc(String username) {
        JSONObject param = CommonUtil.pageParams(this.request);
        return this.systemUserRepository.findSystemUserEntityByUsernameContainingOrderByCreateTimeDesc(username, DataBaseUtil.getPageable(param.getIntValue("page"), param.getIntValue("pageSize"), DataBaseUtil.getSort("desc", "createTime")));
    }
}
